import * as fs from 'fs';
import { FrontendParser } from '../utils/FrontendParser';

/**
 * JavaScript现代化重构工具
 */
export class JavaScriptModernizer {
    
    /**
     * 将ES5代码现代化为ES6+
     */
    async modernizeToES6Plus(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        modernizations: Array<{
            type: string;
            description: string;
            line: number;
            before: string;
            after: string;
        }>;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            modernizations: [] as Array<{
                type: string;
                description: string;
                line: number;
                before: string;
                after: string;
            }>,
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            
            // 分析现代化机会
            const modernizationOpportunities = FrontendParser.analyzeJavaScriptModernization(content);
            
            if (modernizationOpportunities.length === 0) {
                result.message = '代码已经是现代化的，无需更新';
                return result;
            }

            // 执行现代化转换
            const modernizedResult = await this.performES6Modernization(content, modernizationOpportunities);
            
            // 备份原文件
            const backupPath = filePath.replace(/\.js$/, '.es5-backup.js');
            await fs.promises.writeFile(backupPath, content);

            // 写入现代化后的内容
            await fs.promises.writeFile(filePath, modernizedResult.content);

            result.success = true;
            result.message = `成功应用${modernizedResult.modernizations.length}个现代化优化`;
            result.filesModified = [filePath];
            result.modernizations = modernizedResult.modernizations;
            result.appliedChanges = modernizedResult.modernizations.map(m => `${m.type}: ${m.description}`);

        } catch (error) {
            result.errors.push(`现代化失败: ${error}`);
            result.message = `现代化失败: ${error}`;
        }

        return result;
    }

    /**
     * 转换Promise.then为async/await
     */
    async convertToAsyncAwait(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        convertedFunctions: Array<{
            name: string;
            originalCode: string;
            modernizedCode: string;
            line: number;
        }>;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            convertedFunctions: [] as Array<{
                name: string;
                originalCode: string;
                modernizedCode: string;
                line: number;
            }>,
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            
            // 分析Promise.then使用
            const promiseAnalysis = this.analyzePromiseUsage(content);
            
            if (promiseAnalysis.length === 0) {
                result.message = '未发现可以转换为async/await的Promise.then模式';
                return result;
            }

            // 执行async/await转换
            const conversionResult = await this.performAsyncAwaitConversion(content, promiseAnalysis);
            
            // 写入转换后的内容
            await fs.promises.writeFile(filePath, conversionResult.content);

            result.success = true;
            result.message = `成功转换${conversionResult.convertedFunctions.length}个函数为async/await`;
            result.filesModified = [filePath];
            result.convertedFunctions = conversionResult.convertedFunctions;
            result.appliedChanges = conversionResult.convertedFunctions.map(f => `转换函数: ${f.name}`);

        } catch (error) {
            result.errors.push(`async/await转换失败: ${error}`);
            result.message = `转换失败: ${error}`;
        }

        return result;
    }

    /**
     * 优化JavaScript性能
     */
    async optimizeJavaScriptPerformance(filePath: string): Promise<{
        success: boolean;
        message: string;
        filesModified: string[];
        optimizations: Array<{
            type: string;
            description: string;
            applied: boolean;
            impact: 'high' | 'medium' | 'low';
            before?: string;
            after?: string;
        }>;
        appliedChanges: string[];
        errors: string[];
    }> {
        const result = {
            success: false,
            message: '',
            filesModified: [] as string[],
            optimizations: [] as Array<{
                type: string;
                description: string;
                applied: boolean;
                impact: 'high' | 'medium' | 'low';
                before?: string;
                after?: string;
            }>,
            appliedChanges: [] as string[],
            errors: [] as string[]
        };

        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            let optimizedContent = content;
            const optimizations: Array<{
                type: string;
                description: string;
                applied: boolean;
                impact: 'high' | 'medium' | 'low';
                before?: string;
                after?: string;
            }> = [];

            // 1. 优化循环性能
            const loopOptimization = this.optimizeLoops(optimizedContent);
            if (loopOptimization.modified) {
                optimizedContent = loopOptimization.content;
                optimizations.push({
                    type: 'loop-optimization',
                    description: '优化循环性能，缓存数组长度',
                    applied: true,
                    impact: 'medium'
                });
                result.appliedChanges.push('优化循环性能');
            }

            // 2. 优化对象访问
            const objectAccessOptimization = this.optimizeObjectAccess(optimizedContent);
            if (objectAccessOptimization.modified) {
                optimizedContent = objectAccessOptimization.content;
                optimizations.push({
                    type: 'object-access',
                    description: '使用解构赋值优化对象属性访问',
                    applied: true,
                    impact: 'low'
                });
                result.appliedChanges.push('优化对象访问');
            }

            // 3. 添加防抖和节流建议
            const throttleDebounceAnalysis = this.analyzeThrottleDebounceOpportunities(optimizedContent);
            if (throttleDebounceAnalysis.length > 0) {
                optimizations.push({
                    type: 'throttle-debounce',
                    description: `发现${throttleDebounceAnalysis.length}处可以使用防抖或节流的事件处理`,
                    applied: false,
                    impact: 'high'
                });
            }

            // 4. 内存泄漏检测
            const memoryLeakAnalysis = this.analyzeMemoryLeaks(optimizedContent);
            if (memoryLeakAnalysis.length > 0) {
                optimizations.push({
                    type: 'memory-leak',
                    description: `检测到${memoryLeakAnalysis.length}处潜在内存泄漏风险`,
                    applied: false,
                    impact: 'high'
                });
            }

            // 5. 优化字符串操作
            const stringOptimization = this.optimizeStringOperations(optimizedContent);
            if (stringOptimization.modified) {
                optimizedContent = stringOptimization.content;
                optimizations.push({
                    type: 'string-optimization',
                    description: '使用模板字符串替代字符串连接',
                    applied: true,
                    impact: 'low'
                });
                result.appliedChanges.push('优化字符串操作');
            }

            if (optimizedContent !== content) {
                await fs.promises.writeFile(filePath, optimizedContent);
                result.filesModified = [filePath];
            }

            result.success = true;
            result.message = `应用了${result.appliedChanges.length}个性能优化`;
            result.optimizations = optimizations;

        } catch (error) {
            result.errors.push(`JavaScript性能优化失败: ${error}`);
            result.message = `优化失败: ${error}`;
        }

        return result;
    }

    /**
     * 执行ES6现代化转换
     */
    private async performES6Modernization(
        content: string,
        opportunities: Array<{
            type: string;
            suggestion: string;
            line: number;
            original: string;
            modernized: string;
        }>
    ): Promise<{
        content: string;
        modernizations: Array<{
            type: string;
            description: string;
            line: number;
            before: string;
            after: string;
        }>;
    }> {
        let modernizedContent = content;
        const modernizations: Array<{
            type: string;
            description: string;
            line: number;
            before: string;
            after: string;
        }> = [];

        for (const opportunity of opportunities) {
            const originalLine = modernizedContent.split('\n')[opportunity.line - 1];
            
            switch (opportunity.type) {
                case 'es6-arrow':
                    const arrowModernization = this.convertToArrowFunction(originalLine);
                    if (arrowModernization) {
                        modernizedContent = modernizedContent.replace(originalLine, arrowModernization);
                        modernizations.push({
                            type: 'arrow-function',
                            description: '转换为箭头函数',
                            line: opportunity.line,
                            before: originalLine.trim(),
                            after: arrowModernization.trim()
                        });
                    }
                    break;

                case 'template-literal':
                    const templateModernization = this.convertToTemplateLiteral(originalLine);
                    if (templateModernization) {
                        modernizedContent = modernizedContent.replace(originalLine, templateModernization);
                        modernizations.push({
                            type: 'template-literal',
                            description: '使用模板字符串',
                            line: opportunity.line,
                            before: originalLine.trim(),
                            after: templateModernization.trim()
                        });
                    }
                    break;

                case 'const-let':
                    const constLetModernization = this.convertVarToConstLet(originalLine);
                    if (constLetModernization) {
                        modernizedContent = modernizedContent.replace(originalLine, constLetModernization);
                        modernizations.push({
                            type: 'const-let',
                            description: '使用const/let替代var',
                            line: opportunity.line,
                            before: originalLine.trim(),
                            after: constLetModernization.trim()
                        });
                    }
                    break;

                case 'destructuring':
                    const destructuringModernization = this.convertToDestructuring(originalLine);
                    if (destructuringModernization) {
                        modernizedContent = modernizedContent.replace(originalLine, destructuringModernization);
                        modernizations.push({
                            type: 'destructuring',
                            description: '使用解构赋值',
                            line: opportunity.line,
                            before: originalLine.trim(),
                            after: destructuringModernization.trim()
                        });
                    }
                    break;
            }
        }

        return {
            content: modernizedContent,
            modernizations
        };
    }

    private convertToArrowFunction(line: string): string | null {
        // 将 function 表达式转换为箭头函数
        const functionMatch = line.match(/^(\s*)(const|let|var)\s+(\w+)\s*=\s*function\s*\(([^)]*)\)\s*\{/);
        if (functionMatch) {
            const [, indent, declaration, name, params] = functionMatch;
            return `${indent}${declaration} ${name} = (${params}) => {`;
        }
        return null;
    }

    private convertToTemplateLiteral(line: string): string | null {
        // 将字符串连接转换为模板字符串
        const stringConcatPattern = /(['"])((?:(?!\1)[^\\]|\\.)*)(\1)\s*\+\s*([^+;]+)(?:\s*\+\s*(['"])((?:(?!\5)[^\\]|\\.)*)(\5))?/;
        const match = line.match(stringConcatPattern);
        
        if (match) {
            const variable = match[4].trim();
            const beforeString = match[2];
            const afterString = match[6] || '';
            
            return line.replace(
                match[0],
                `\`${beforeString}\${${variable}}${afterString}\``
            );
        }
        return null;
    }

    private convertVarToConstLet(line: string): string | null {
        if (line.includes('var ')) {
            // 简单替换：假设没有重新赋值的用const，否则用let
            if (line.includes('=') && !line.includes('++') && !line.includes('--')) {
                return line.replace('var ', 'const ');
            } else {
                return line.replace('var ', 'let ');
            }
        }
        return null;
    }

    private convertToDestructuring(line: string): string | null {
        // 转换对象属性访问为解构
        const objectAccessMatch = line.match(/^(\s*)(const|let|var)\s+(\w+)\s*=\s*(\w+)\.(\w+);?/);
        if (objectAccessMatch) {
            const [, indent, declaration, varName, objName, propName] = objectAccessMatch;
            
            if (varName === propName) {
                return `${indent}${declaration} { ${propName} } = ${objName};`;
            } else {
                return `${indent}${declaration} { ${propName}: ${varName} } = ${objName};`;
            }
        }
        return null;
    }

    private analyzePromiseUsage(content: string): Array<{
        functionName: string;
        startLine: number;
        endLine: number;
        promiseChain: string;
    }> {
        const promiseUsages: Array<{
            functionName: string;
            startLine: number;
            endLine: number;
            promiseChain: string;
        }> = [];

        const lines = content.split('\n');
        
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            
            // 查找包含.then的行
            if (line.includes('.then(') && !line.includes('await')) {
                const functionMatch = this.findContainingFunction(lines, i);
                if (functionMatch) {
                    const promiseChain = this.extractPromiseChain(lines, i);
                    
                    promiseUsages.push({
                        functionName: functionMatch.name,
                        startLine: functionMatch.startLine,
                        endLine: functionMatch.endLine,
                        promiseChain
                    });
                }
            }
        }

        return promiseUsages;
    }

    private findContainingFunction(lines: string[], lineIndex: number): {name: string; startLine: number; endLine: number} | null {
        // 向上查找函数定义
        for (let i = lineIndex; i >= 0; i--) {
            const line = lines[i];
            const functionMatch = line.match(/function\s+(\w+)|(\w+)\s*[:=]\s*function|(\w+)\s*[:=]\s*\([^)]*\)\s*=>/);
            
            if (functionMatch) {
                const functionName = functionMatch[1] || functionMatch[2] || functionMatch[3] || 'anonymous';
                const endLine = this.findFunctionEnd(lines, i);
                
                return {
                    name: functionName,
                    startLine: i + 1,
                    endLine
                };
            }
        }
        return null;
    }

    private findFunctionEnd(lines: string[], startIndex: number): number {
        let braceCount = 0;
        let foundOpenBrace = false;
        
        for (let i = startIndex; i < lines.length; i++) {
            const line = lines[i];
            
            for (const char of line) {
                if (char === '{') {
                    braceCount++;
                    foundOpenBrace = true;
                } else if (char === '}') {
                    braceCount--;
                    
                    if (foundOpenBrace && braceCount === 0) {
                        return i + 1;
                    }
                }
            }
        }
        
        return startIndex + 1;
    }

    private extractPromiseChain(lines: string[], startIndex: number): string {
        let promiseChain = '';
        let i = startIndex;
        
        while (i < lines.length) {
            const line = lines[i].trim();
            promiseChain += line + '\n';
            
            if (line.includes('.catch(') || line.includes(';')) {
                break;
            }
            i++;
        }
        
        return promiseChain.trim();
    }

    private async performAsyncAwaitConversion(
        content: string,
        promiseAnalysis: Array<{functionName: string; startLine: number; endLine: number; promiseChain: string}>
    ): Promise<{
        content: string;
        convertedFunctions: Array<{
            name: string;
            originalCode: string;
            modernizedCode: string;
            line: number;
        }>;
    }> {
        let convertedContent = content;
        const convertedFunctions: Array<{
            name: string;
            originalCode: string;
            modernizedCode: string;
            line: number;
        }> = [];

        for (const analysis of promiseAnalysis) {
            const originalCode = analysis.promiseChain;
            const modernizedCode = this.convertPromiseChainToAsyncAwait(originalCode);
            
            if (modernizedCode) {
                // 替换函数声明为async
                const lines = convertedContent.split('\n');
                const functionLine = lines[analysis.startLine - 1];
                
                if (!functionLine.includes('async')) {
                    const asyncFunctionLine = this.addAsyncToFunction(functionLine);
                    lines[analysis.startLine - 1] = asyncFunctionLine;
                    convertedContent = lines.join('\n');
                }
                
                // 替换Promise链
                convertedContent = convertedContent.replace(originalCode, modernizedCode);
                
                convertedFunctions.push({
                    name: analysis.functionName,
                    originalCode,
                    modernizedCode,
                    line: analysis.startLine
                });
            }
        }

        return {
            content: convertedContent,
            convertedFunctions
        };
    }

    private convertPromiseChainToAsyncAwait(promiseChain: string): string | null {
        // 简化的Promise.then转async/await转换
        try {
            let converted = promiseChain;
            
            // 替换.then()调用
            converted = converted.replace(
                /(\w+)\.then\(\s*([^)]+)\s*\)/g,
                'const result = await $1;\n    $2(result)'
            );
            
            // 替换.catch()调用
            converted = converted.replace(
                /\.catch\(\s*([^)]+)\s*\)/g,
                'try {\n    // await logic here\n  } catch (error) {\n    $1(error);\n  }'
            );
            
            return converted;
        } catch (error) {
            return null;
        }
    }

    private addAsyncToFunction(functionLine: string): string {
        if (functionLine.includes('function')) {
            return functionLine.replace('function', 'async function');
        } else if (functionLine.includes('=>')) {
            return functionLine.replace(/(\w+\s*[:=]\s*)(\([^)]*\)\s*=>)/, '$1async $2');
        }
        return functionLine;
    }

    private optimizeLoops(content: string): {modified: boolean; content: string} {
        let modified = false;
        let optimized = content;
        
        // 优化for循环：缓存数组长度
        const forLoopPattern = /for\s*\(\s*let\s+(\w+)\s*=\s*0;\s*\1\s*<\s*(\w+)\.length;\s*\1\+\+\s*\)/g;
        const matches = content.match(forLoopPattern);
        
        if (matches) {
            for (const match of matches) {
                const loopMatch = match.match(/for\s*\(\s*let\s+(\w+)\s*=\s*0;\s*\1\s*<\s*(\w+)\.length;\s*\1\+\+\s*\)/);
                if (loopMatch) {
                    const [, indexVar, arrayVar] = loopMatch;
                    const optimizedLoop = `for (let ${indexVar} = 0, len = ${arrayVar}.length; ${indexVar} < len; ${indexVar}++)`;
                    optimized = optimized.replace(match, optimizedLoop);
                    modified = true;
                }
            }
        }
        
        return {modified, content: optimized};
    }

    private optimizeObjectAccess(content: string): {modified: boolean; content: string} {
        let modified = false;
        let optimized = content;
        
        // 查找重复的对象属性访问
        const objectAccessPattern = /(\w+)\.(\w+)/g;
        const accessCounts: Record<string, number> = {};
        let match;
        
        while ((match = objectAccessPattern.exec(content)) !== null) {
            const access = match[0];
            accessCounts[access] = (accessCounts[access] || 0) + 1;
        }
        
        // 对出现3次以上的对象访问建议解构
        for (const [access, count] of Object.entries(accessCounts)) {
            if (count >= 3) {
                const [objName, propName] = access.split('.');
                const destructuringLine = `const { ${propName} } = ${objName}; // 优化：避免重复访问 ${access}`;
                
                // 在第一次使用前添加解构声明
                const firstUsageIndex = optimized.indexOf(access);
                if (firstUsageIndex !== -1) {
                    const lines = optimized.split('\n');
                    const lineIndex = optimized.substring(0, firstUsageIndex).split('\n').length - 1;
                    lines.splice(lineIndex, 0, `  ${destructuringLine}`);
                    optimized = lines.join('\n');
                    modified = true;
                }
            }
        }
        
        return {modified, content: optimized};
    }

    private analyzeThrottleDebounceOpportunities(content: string): Array<{
        eventType: string;
        line: number;
        suggestion: string;
    }> {
        const opportunities: Array<{
            eventType: string;
            line: number;
            suggestion: string;
        }> = [];
        
        const lines = content.split('\n');
        const highFrequencyEvents = ['scroll', 'resize', 'mousemove', 'keypress'];
        
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            
            for (const eventType of highFrequencyEvents) {
                if (line.includes(`'${eventType}'`) || line.includes(`"${eventType}"`)) {
                    const needsThrottling = eventType === 'scroll' || eventType === 'resize' || eventType === 'mousemove';
                    const needsDebouncing = eventType === 'keypress';
                    
                    opportunities.push({
                        eventType,
                        line: i + 1,
                        suggestion: needsThrottling ? '建议使用节流(throttle)' : '建议使用防抖(debounce)'
                    });
                }
            }
        }
        
        return opportunities;
    }

    private analyzeMemoryLeaks(content: string): Array<{
        type: string;
        line: number;
        description: string;
    }> {
        const leaks: Array<{
            type: string;
            line: number;
            description: string;
        }> = [];
        
        const lines = content.split('\n');
        
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            
            // 检测未清理的事件监听器
            if (line.includes('addEventListener') && !content.includes('removeEventListener')) {
                leaks.push({
                    type: 'event-listener',
                    line: i + 1,
                    description: '事件监听器可能未被移除，可能导致内存泄漏'
                });
            }
            
            // 检测未清理的定时器
            if ((line.includes('setInterval') || line.includes('setTimeout')) && !content.includes('clear')) {
                leaks.push({
                    type: 'timer',
                    line: i + 1,
                    description: '定时器可能未被清理，可能导致内存泄漏'
                });
            }
            
            // 检测闭包中的大对象引用
            if (line.includes('function') && line.includes('return') && content.includes('var ')) {
                leaks.push({
                    type: 'closure',
                    line: i + 1,
                    description: '闭包可能持有不必要的大对象引用'
                });
            }
        }
        
        return leaks;
    }

    private optimizeStringOperations(content: string): {modified: boolean; content: string} {
        let modified = false;
        let optimized = content;
        
        // 将字符串连接转换为模板字符串
        const stringConcatPattern = /(['"])((?:(?!\1)[^\\]|\\.)*)(\1)\s*\+\s*([^+;'"]+)(?:\s*\+\s*(['"])((?:(?!\5)[^\\]|\\.)*)(\5))?/g;
        
        optimized = optimized.replace(stringConcatPattern, (match, quote1, str1, quote1End, variable, quote2, str2) => {
            if (str2) {
                return `\`${str1}\${${variable.trim()}}${str2}\``;
            } else {
                return `\`${str1}\${${variable.trim()}}\``;
            }
        });
        
        if (optimized !== content) {
            modified = true;
        }
        
        return {modified, content: optimized};
    }
}